#include "stlmainwindow.h"
#include "ui_stlmainwindow.h"

STLMainWindow::STLMainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::STLMainWindow)
{
    ui->setupUi(this);
    iniUI();
    m_sp_stl_reader = std::make_shared<STLReader>();
}

STLMainWindow::~STLMainWindow()
{
    delete ui;
}

void STLMainWindow::iniUI()
{
    fLabCurFile = new QLabel;
    fLabCurFile->setMinimumWidth(150);
    fLabCurFile->setText("当前文件：");
    ui->statusbar->addWidget(fLabCurFile);

    ui->actionPreview->setEnabled(false);
    ui->actionSaveAs->setEnabled(false);
    ui->actionQuickSlicingSetting->setEnabled(false);
    ui->actionSetupSliceInfo->setEnabled(false);
    ui->actionSliceModel->setEnabled(false);
    ui->actionModelColorSetting->setEnabled(false);
    ui->actionGrayScaleConvertion->setEnabled(false);
    ui->actionViewPortMatched->setEnabled(false);
    ui->actionViewPortFilled->setEnabled(false);
}

void STLMainWindow::updateUI()
{
    // 启用定向预览菜单选项
    ui->actionPreview->setEnabled(true);
    ui->actionSaveAs->setEnabled(true);
    ui->actionQuickSlicingSetting->setEnabled(true);
    ui->actionSetupSliceInfo->setEnabled(true);
    ui->actionSliceModel->setEnabled(true);
    ui->actionModelColorSetting->setEnabled(true);
    ui->actionGrayScaleConvertion->setEnabled(true);
    ui->actionViewPortMatched->setEnabled(true);
    ui->actionViewPortFilled->setEnabled(true);
}

void STLMainWindow::initModelWidget()
{
    m_sp_snapShotSetting.reset();
    m_sp_modelColorPalette.reset();
    m_sp_previewDirectionSelector.reset();
    m_sp_slicingSettingDialog.reset();
    m_sp_sliceWidget.reset();
    m_sp_modelWidget.reset();
    m_sp_modelWidget = std::make_shared<STLModelWidget>(m_sp_stl_reader, this);
    m_sp_slicingSettingDialog = std::make_shared<SlicingSettingsDialog>(m_sp_modelWidget.get());
    m_sp_previewDirectionSelector = std::make_shared<PreviewDirectionSelector>(m_sp_modelWidget);
    m_sp_modelColorPalette = std::make_shared<ModelColorPalette>(m_sp_modelWidget.get());
    m_sp_snapShotSetting = std::make_shared<SnapShotSettingDialog>(m_sp_modelWidget.get());
    setCentralWidget(m_sp_modelWidget.get());

    m_sp_modelWidget->show();
}

void STLMainWindow::updateCurrentFileLabel(const QString &stl_file_path)
{
    QFileInfo fileInfo(stl_file_path);
    QString fileName = fileInfo.fileName();

    // 更新文件名显示
    fLabCurFile->setText(QString("当前文件: %1").arg(fileName));
    fLabCurFile->setToolTip(stl_file_path);

    // 更新文件大小显示
    qint64 size = fileInfo.size();
    QString sizeText;
    // if (size < 1024) {
    //     sizeText = QString("%1 字节").arg(size);
    // } else if (size < 1024 * 1024) {
    //     sizeText = QString("%1 KB").arg(size / 1024);
    // } else {
    //     sizeText = QString("%1 MB").arg(size / (1024 * 1024), 1, 'f', 2);
    // }

    // 更新窗口标题
    setWindowTitle(QString("%1 - STL Viewer").arg(fileName));
}

void STLMainWindow::createSlicingWindow(SliceInfo slice_info)
{
    // 创建切片窗口（设置父对象为模型控件）
    m_sp_sliceWidget = std::make_shared<SliceMainWindow>(m_sp_modelWidget.get());

    // 初始化切片控件
    m_sp_sliceWidget->initSliceWidget(m_sp_stl_reader, slice_info);

    // 设置窗口属性
    m_sp_sliceWidget->setWindowTitle("切片视图");
    m_sp_sliceWidget->setWindowFlags(Qt::Window);
    m_sp_sliceWidget->resize(this->width(), this->height());

    // 设置信号槽
    connect(m_sp_sliceWidget.get(), &SliceMainWindow::deliverAllContours, this, &STLMainWindow::on_allContours_delivered);

    // 显示窗口
    m_sp_sliceWidget->show();
}

void STLMainWindow::handleSlicingSettings(const QVector3D& planeNormal, const QVector3D& cameraUp, float cameraDistance, float slicingStride)
{
    // 创建切片信息结构
    SliceInfo sliceInfo;
    sliceInfo.plane_norm = planeNormal;/*m_sp_modelWidget->transformNormalToModelSpace(planeNormal);*/
    sliceInfo.camera_up = cameraUp;
    sliceInfo.distance = cameraDistance;
    sliceInfo.thickness = slicingStride;

    // 创建切片窗口
    createSlicingWindow(sliceInfo);
}

/************槽函数定义**************/

void STLMainWindow::on_actionOpenSTL_triggered()
{
    // 获取用户选择的文件路径
    QString filePath = QFileDialog::getOpenFileName(this, tr("打开STL文件"), QDir::homePath(), tr("STL文件 (*.stl *.STL);;所有文件 (*.*)"));

    if (filePath.isEmpty())
        return;  // 用户取消了选择

    try {
        // 尝试读取STL文件
        bool success = m_sp_stl_reader->readMeshesFromSTLFile(filePath, STL_READ_TYPE::BINARY);
        if (!success)
        {
            QMessageBox::warning(this, tr("错误"), tr("无法读取STL文件"));
            return;
        }

        // 文件读取成功，初始化模型显示控件
        initModelWidget();

        // 修改状态栏文本
        updateCurrentFileLabel(filePath);

        // 更新整体UI
        updateUI();

    } catch (const std::exception &e) {
        QMessageBox::critical(this, tr("错误"),
                              tr("读取STL文件时发生错误: %1").arg(e.what()));
    }
}

void STLMainWindow::on_actionSliceModel_triggered()
{
    QVector3D camera_pos = m_sp_modelWidget->getCurrentCameraPos();
    QVector3D plane_norm = camera_pos.normalized();
    QVector3D camera_up = m_sp_modelWidget->getCurrentCameraUp();
    float camera_dis = camera_pos.length();
    float stride = 0.1f;

    SliceInfo slice_info = {plane_norm, camera_up, camera_dis, stride};

    createSlicingWindow(slice_info);
}

void STLMainWindow::on_actionSetupSliceInfo_triggered()
{
    QVector3D camera_up = m_sp_modelWidget->getCurrentCameraUp();
    m_sp_slicingSettingDialog->setWindowTitle("设置切片信息");
    m_sp_slicingSettingDialog->setWindowFlags(Qt::Window);
    m_sp_slicingSettingDialog->resize(this->width() / 2, this->height() / 2);
    m_sp_slicingSettingDialog->setCameraUp(camera_up);
    disconnect(m_sp_slicingSettingDialog.get(), &SlicingSettingsDialog::slicingSettingsConfirmed, nullptr, nullptr);
    connect(m_sp_slicingSettingDialog.get(), &SlicingSettingsDialog::slicingSettingsConfirmed,
            this, &STLMainWindow::handleSlicingSettings);
    m_sp_slicingSettingDialog->show();
}

void STLMainWindow::on_actionSaveAs_triggered()
{
    m_sp_snapShotSetting->show();
    disconnect(m_sp_snapShotSetting.get(), &SnapShotSettingDialog::accepted, nullptr, nullptr); // TODO(mengjinlang): 权宜之计，否则会多次触发，整理代码时再把connect放好，主要难点时各指针初始化时机难以统一
    connect(m_sp_snapShotSetting.get(), &SnapShotSettingDialog::accepted, this, [this](){
        qsizetype res_width = m_sp_snapShotSetting->getResWidth();
        qsizetype res_height = m_sp_snapShotSetting->getResHeight();
        auto file_name = m_sp_snapShotSetting->getFileName();
        auto file_format = m_sp_snapShotSetting->getFileFormat(); // TODO(mengjinlang): 需要一个文件管理类，重构存储接口才用得上（目前只支持PNG），先留着
        m_sp_modelWidget->saveFramebufferToPNG(file_name + "." + file_format, res_width, res_height);
    });
}

void STLMainWindow::on_actionPreview_triggered()
{
    m_sp_previewDirectionSelector->show();
}

void STLMainWindow::on_actionQuickSlicingSetting_triggered()
{
    QVector3D camera_pos = m_sp_modelWidget->getCurrentCameraPos();
    QVector3D plane_norm = camera_pos.normalized();
    QVector3D camera_up = m_sp_modelWidget->getCurrentCameraUp();
    float camera_dis = camera_pos.length();

    m_sp_slicingSettingDialog->setWindowTitle("设置切片信息");
    m_sp_slicingSettingDialog->setWindowFlags(Qt::Window);
    m_sp_slicingSettingDialog->resize(this->width() / 2, this->height() / 2);
    m_sp_slicingSettingDialog->setPlaneNormal(plane_norm);
    m_sp_slicingSettingDialog->setCameraDistance(camera_dis);
    m_sp_slicingSettingDialog->setCameraUp(camera_up);
    disconnect(m_sp_slicingSettingDialog.get(), &SlicingSettingsDialog::slicingSettingsConfirmed, nullptr, nullptr);
    connect(m_sp_slicingSettingDialog.get(), &SlicingSettingsDialog::slicingSettingsConfirmed,
            this, &STLMainWindow::handleSlicingSettings);
    m_sp_slicingSettingDialog->show();
}

void STLMainWindow::on_allContours_delivered(const QVector<QVector<QVector<QPointF>>>& all_contours)
{
    qDebug() << QString("一共有 %1 层").arg(all_contours.size());
    for(const auto& slice : all_contours)
    {
        int i = &slice - &all_contours[0];
        qDebug() << QString("第 %1 层有 %2 个轮廓").arg(i).arg(slice.size());
        for(const auto& contour : slice)
        {
            int j = &contour - &slice[0];
            qDebug() << QString("其中第 %1 个轮廓有 %2 个点").arg(j).arg(contour.size());
        }
    }
    emit sendAllContours(all_contours);
}

void STLMainWindow::on_actionModelColorSetting_triggered()
{
    m_sp_modelColorPalette->openColorDialog();
    disconnect(m_sp_modelColorPalette.get(), &ModelColorPalette::colorConfirmed, nullptr, nullptr);
    connect(m_sp_modelColorPalette.get(), &ModelColorPalette::colorConfirmed, m_sp_modelWidget.get(), &STLModelWidget::setPureColor);
}

void STLMainWindow::on_actionGrayScaleConvertion_triggered()
{
    m_sp_modelWidget->applyGrayscaleValues();
}

void STLMainWindow::on_actionViewPortMatched_triggered()
{
    m_sp_modelWidget->setModelViewPortMatched();
}


void STLMainWindow::on_actionViewPortFilled_triggered()
{
    m_sp_modelWidget->setModelViewPortFilled(this->width(), this->height(), ProjectionType::Perspective);
}

